The invention is generally related to integrated circuit device design and architecture, and in particular, to the processing of switch instructions on a bytecode instruction processor.
Platform-independent programming languages, such as the xe2x80x9cJavaxe2x80x9d programming language from Sun Microsystems, Inc. offer significant advantages over traditional, platform-specific languages. A platform-independent programming language typically utilizes platform-independent program code (machine-readable instructions) suitable for execution on multiple hardware platforms without regard for the particular instruction set for the hardware platforms. A hardware platform typically includes a computer system having one or more processors (e.g., microprocessors or microcontrollers) which execute a particular set of instructions having a specific format, sometimes referred to as a native instruction set. This is in contrast to platform-specific languages, which utilize platform-specific compilers to generate program code that is native to one particular hardware platform. While the same source code may in some instances be compiled by different platform-specific compilers into suitable program code for multiple platforms, the resulting program code is not platform-independent.
In many environments, platform-independent program codes are in an intermediate code format, since further processing is required to execute such codes on a specific hardware platform. For Java, for example, the intermediate codes are referred to as bytecodes. Typically, a compiler is used to generate a series of intermediate codes from a source file. The intermediate codes are then executed by a software interpreter (known as a Java Virtual Machine (JVM)) that converts them into native instructions for the computer system on the fly. Consequently, the intermediate codes are executable on any computer system having a suitable platform-independent program code interpreter.
Many platform-independent program codes are typically relatively compact, which makes them readily suited for downloading over a network or modem. Moreover, since the program code is platform-independent, the downloading computer system (or server) can download the same program code irrespective of the particular hardware platform of the executing computer system (or client). Consequently, platform-independent program codes such as Java have begun to enjoy immense popularity for the distribution of software programs over the Internet. Typically, platform-independent software programs downloaded from the Internet are in the form of applets which execute within a web browser. It should be understood, however, that platform-independent program codes have many other uses, including in stand-alone applications, operating systems, and real-time embedded systems, among others.
One problem with platform-independent program code, however, is that the program code often must be interpreted during run time, which significantly reduces execution speed compared to program code native to a particular hardware platform. Some JVM""s, for example, may require up to 50 processor clock cycles to process each bytecode, compared to typically one clock cycle for most native instructions.
As an alternative to run time interpretation, software-based just-in-time (JIT) compilers have been developed to optimize interpretation of platform-independent program code, typically by emulating the functionality of the platform-independent code using native code. While execution speed is increased over simple runtime interpretation, the platform-independent program code is still slower than native code, and additional memory space is required to store the compiler code.
At the other extreme, dedicated stand-alone Java processors have been proposed to utilize platform-independent instructions as their native instruction set. While these processors have the capability of running platform-independent program code as fast as other native program codes for other hardware platforms, the processors suffer from the same problems as any other processor when executing non-native program code.
It has also been proposed to combine a native instruction processor with a Java coprocessor or a hardware translation circuit to accelerate the processing of Java bytecodes. In the former instance, a Java coprocessor will typically be under the control of a native processor, and will be called upon whenever Java program code needs to be executed. In the latter instance, a translation circuit will attempt to capture Java bytecodes and translate the bytecodes into native instructions so that, when Java program code is requested by a native processor, the instructions returned to the native processor in response to the request will be in a format native to the processor.
In either instance, often only a subset of the Java bytecodes are supported by the coprocessor or hardware translation circuit, typically due to the complexities and additional circuitry that would otherwise be required to support all of the Java bytecode instruction set. Java is a stack-based language, which is often difficult to efficiently implement in hardware. Moreover, some of the more complex instructions would require an inordinate amount of custom circuitry to be implemented in hardware considering their relatively infrequent occurrence in typical Java computer programs. For each instruction, a tradeoff inherently exists between the additional cost of implementing the instruction in hardware and the additional gain in performance that would be achieved.
For instructions that are not directly implemented in hardware, typically a JVM executing on the native processor handles those instructions, often with a significant performance penalty. To handle a non-implemented instruction in a coprocessor arrangement, for example, control must be passed from the coprocessor to the native processor, the instruction must be interpreted by the JVM executing on the native processor, and control must be returned to the Java processor.
Consequently, a significant need exists in the art for a manner of implementing as many Java bytecode instructions in hardware as possible, thus minimizing the frequency of instructions requiring JVM interpretation.
One particular type of instruction that is difficult to implement in hardware is a switch instruction. Java, for example, supports two types of switch instructions, a lookupswitch instruction and a tableswitch instruction, each of which operates in a similar manner of a xe2x80x9ccasexe2x80x9d statement supported by many programming languages.
For example, a lookupswitch instruction typically includes a number of match-offset pairs that define a plurality of tests that are applied to a key value that has been pushed onto the stack prior to the instruction. Each match-offset pair includes a match value that the key value is compared to, and an associated offset value that is used to calculate a target address that is jumped to whenever a match occurs with the associated match value. To execute this instruction the JVM pops the key off the stack and compares it to each match value. If the key is equal to one of the match values, the JVM calculates a target address by adding the offset associated with the matching match value to the address of the lookupswitch bytecode. The JVM jumps to the target address and continues execution there. If none of the match values are equal to the key, the JVM jumps to a default target address that is also specified by the lookupswitch instruction.
A tableswitch instruction is similar to a lookupswitch instruction, except that rather than specifying match-offset pairs, a range of match values is specified by low and high values defined by the instruction. A list of offset values, equal to the number of match values defined in the range, is also specified by the instruction. To execute this instruction the JVM pops the key off the operand stack and compares it to the low and high values, and uses an offset value corresponding to the matching value in the specified range to calculate the target address that is jumped to by the JVM. If the key is less than the low value and greater than the high value, a default offset, also specified by the instruction, is used to calculate the target address.
Both types of Java switch instructions are difficult to implement in hardware, as both are variable in length, and both require a substantial amount of processing to perform the sequential tests that are needed to fully implement the instructions. Thus, often these types of instructions are executed by passing control to a software JVM, thereby increasing the processing overhead of such instructions and decreasing system performance.
Therefore, a substantial need exists in the art for a manner of improving the performance of a data processing system in executing switch instructions such as Java lookupswitch and tableswitch bytecode instructions.
The invention addresses these and other problems associated with the prior art by providing a circuit arrangement and method that facilitate the execution of switch instructions such as Java lookupswitch and tableswitch instructions in hardware through emulation of such instructions using a plurality of conditional branch instructions from the same instruction set as the switch instructions, and which are capable of being directly implemented in hardware. The conditional branch instructions are typically generated by switch instruction handling logic (which may be implemented within the instruction fetch logic) and passed to execution logic capable of natively executing the conditional branch instructions.
By emulating a complex switch instruction in switch instruction handling logic using a plurality of conditional branch instructions from the same instruction set, often the amount of custom circuitry needed to fully support a complex switch instruction is substantially reduced from what would be required to natively support the switch instruction in the execution logic of a hardware processor. Moreover, compared to software emulation, which typically requires passing control to a software interpreter, the overhead associated with emulating a switch instruction in the instruction fetch logic using multiple conditional branch instructions capable of being natively executed by execution logic offers substantial gains in performance.
In one embodiment consistent with the invention, for example, Java lookupswitch and tableswitch instructions are emulated by generating a plurality of Java ifeq bytecode instructions in instruction fetch logic for execution by execution logic that natively supports ifeq bytecode instructions. Moreover, to simplify stack management, one or more dup bytecode instructions are also generated to duplicate the key value for a lookupswitch or tableswitch instruction on the stack so that the key value is available for each ifeq bytecode instruction. An unconditional branch instruction, e.g., a goto_w bytecode instruction, may also be generated to emulate the default branch of a lookupswitch or tableswitch instruction.
These and other advantages and features, which characterize the invention, are set forth in the claims annexed hereto and forming a further part hereof. However, for a better understanding of the invention, and of the advantages and objectives attained through its use, reference should be made to the Drawings, and to the accompanying descriptive matter, in which there is described exemplary embodiments of the invention.